import { requestMethods } from "../core/constants";
import { HttpMethod } from "../types/options";
import { RetryOptions } from "../types/retry";

/**
 规范化 HTTP 请求方法。

 将输入的请求转换为标准格式，仅针对已知的 HTTP 方法。
 */
export const normalizeRequestMethod = (input: string): string =>
	requestMethods.includes(input as HttpMethod) ? input.toUpperCase() : input

/**
 定义默认允许重试的 HTTP 方法列表。

 这些方法通常是幂等的（重复执行不会产生副作用）。
 */
const retryMethods = ['get', 'put', 'head', 'delete', 'options', 'trace']

/**
 触发重试的 HTTP 状态码列表。

 这些状态码通常表示临时错误，重试可能成功。
 */
const retryStatusCodes = [408, 413, 429, 500, 502, 503, 504]

/**
 需要根据 Retry-After 响应头决定重试时机的状态码。

 服务器会通过 Retry-After 头指定建议的重试等待时间。
 */
const retryAfterStatusCodes = [413, 429, 503]

/**
 默认的重试配置选项

 定义了重试机制的各种参数默认值
 */
const defaultRetryOptions: Required<RetryOptions> = {
	limit: 2,
	methods: retryMethods,
	statusCodes: retryStatusCodes,
	afterStatusCodes: retryAfterStatusCodes,
	maxRetryAfter: Number.POSITIVE_INFINITY,
	backoffLimit: Number.POSITIVE_INFINITY,
	delay: attemptCount => 0.3 * (2 ** (attemptCount - 1)) * 1000,
};

/**
 规范化重试配置选项
 
 将用户提供的配置与默认配置合并，并进行基本验证
 */
export const normalizeRetryOptions = (retry: number | RetryOptions = {}): Required<RetryOptions> => {
	if (typeof retry === 'number') {
		return {
			...defaultRetryOptions,
			limit: retry,
		}
	}

	if (retry.methods && !Array.isArray(retry.methods)) {
		throw new Error('retry.methods must be an array')
	}

	if (retry.statusCodes && !Array.isArray(retry.statusCodes)) {
		throw new Error('retry.statusCodes must be an array')
	}

	return {
		...defaultRetryOptions,
		...retry,
	}
};